Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First implementation of PDF viewer feature #138

Merged
merged 23 commits into from
Nov 20, 2018
Merged

Conversation

mneuwert
Copy link
Contributor

@mneuwert mneuwert commented Oct 29, 2018

Description

PDF viewer shall be implemented allowing comfortable viewing of PDF files.

Related Issue

#87

Motivation and Context

We would like to utilise PDFKit features to provide user experience similar to iBooks app while browsing PDF files.

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • PDF viewer with thumbnail view which can be hidden
  • Go to page X feature
  • Search feature showing the hits with page numbers and allowing to jump to selected search hit
  • Separate PDF navigation screen with two tabs: table of contents / larger thumbnails for all pages

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@CLAassistant
Copy link

CLAassistant commented Oct 29, 2018

CLA assistant check
Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ mneuwert
❌ felix-schwarz
You have signed the CLA already but the status is still pending? Let us recheck it.

@mneuwert mneuwert added the p2-high Escalation, on top of current planning, release blocker label Oct 29, 2018
@mneuwert mneuwert added this to the 0.1.0 milestone Oct 29, 2018
@mneuwert mneuwert mentioned this pull request Oct 29, 2018
10 tasks
@codecov
Copy link

codecov bot commented Oct 29, 2018

Codecov Report

Merging #138 into master will increase coverage by <.01%.
The diff coverage is 0.26%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #138      +/-   ##
==========================================
+ Coverage   24.83%   24.84%   +<.01%     
==========================================
  Files          88       88              
  Lines        7493     7442      -51     
==========================================
- Hits         1861     1849      -12     
+ Misses       5632     5593      -39
Impacted Files Coverage Δ
ownCloud/Viewer/PDFViewerViewController.swift 0% <0%> (ø) ⬆️
ownCloud/Viewer/PDFTocTableViewController.swift 0% <0%> (ø) ⬆️
ownCloud/Viewer/PDFOutlineViewController.swift 0% <0%> (ø) ⬆️
ownCloud/Viewer/PDFTocTableViewCell.swift 0% <0%> (ø) ⬆️
ownCloud/Viewer/PDFSearchTableViewCell.swift 0% <0%> (ø) ⬆️
ownCloud/UIKit Extensions/String+Extension.swift 40% <0%> (-60%) ⬇️
ownCloud/Viewer/PDFSearchViewController.swift 0% <0%> (ø) ⬆️
ownCloud/Viewer/PDFTocItem.swift 0% <0%> (ø) ⬆️
...nCloud/Viewer/PDFThumbnailCollectionViewCell.swift 0% <0%> (ø) ⬆️
...Viewer/PDFThumbnailsCollectionViewController.swift 0% <0%> (ø) ⬆️
... and 2 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ce6ad46...1445b36. Read the comment docs.

- Fixed swiftlint warnings
- Added missing removal of block-based notification observer and made the block hold self as weak reference, so it can't cause a retain cycle
self.contentView.addSubview(pageLabel)

titleLabel.font = UIFont.systemFont(ofSize: titleFontSize, weight: UIFont.Weight.regular)
titleLabel.adjustsFontSizeToFitWidth = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value is already set to false. see adjustFontSizeToFitWidth

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu yes, this line can be removed. The intention was to make the code more explicit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu fixed

return
}
DispatchQueue.main.async {
if let cell : PDFThumbnailCollectionViewCell = self.collectionView?.cellForItem(at: indexPath) as? PDFThumbnailCollectionViewCell {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this in multiple places and it's only my preference of styling things, but you can chain if let and avoid a los of { }

Something like:

if let cell : PDFThumbnailCollectionViewCell = self.collectionView?.cellForItem(at: indexPath) as? PDFThumbnailCollectionViewCell, 
   let visibleCells = self.collectionView?.visibleCells,
   visibleCells.contains(cell) {
                            cell.imageView?.image = thumbnailImage
                            cell.pageLabel?.text = page.label
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu yes, true. I can change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu I checked once again, here chaining would sacrifice readability and in fact I only found one single other piece of code where chaining could have been applied.

fileprivate let ANIMATION_DUR = 0.25
fileprivate let THUMBNAIL_VIEW_WIDTH_MULTIPLIER: CGFloat = 0.15
fileprivate let THUMBNAIL_VIEW_HEIGHT_MULTIPLIER: CGFloat = 0.1
fileprivate let FILENAME_CONTAINER_TOP_MARGIN: CGFloat = 10.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen that in some places you code constants in different styles, is there some reason to do it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu for me it was not clear if we have any official coding conventions and I didn't find an example of constants in existing code. What is the preferred style?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, we don't have any rule defined for this neither any complete style guide apart of what we have in the SwiftLint file.

I think we can discuss the style guide in the new opened issue here #139

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pablocarmu fixed

@felix-schwarz
Copy link
Contributor

I found a couple of glitches worth fixing before diving into code review:

  1. the name of the file is currently shown in the navigation bar and in an overlay. Having it in the navigation bar should be sufficient:

bildschirmfoto 2018-10-30 um 12 31 53

  1. Tapping on the table of contents, a white background shows when dragging the table view down or up beyond its upper and lower end (rubberband-style):

bildschirmfoto 2018-10-30 um 12 35 26 2

The background has the correct color after switching to the the icon view and back.

  1. When I search for something and tap on a hit, I see the search interface dismissing twice.

  2. While entering something in search, the separator lines are moving around unexpectedly after every keystroke.

  3. tapping on the page dismisses the navigation bar, but leads to a jumpy animation for both the page view and the thumbnails.

  4. The page is cut off at the top and bottom when zooming in:

bildschirmfoto 2018-10-30 um 12 40 28
bildschirmfoto 2018-10-30 um 12 40 22

  1. If I zoom into a page and then tap it, the zoom resets while going in/out of full screen mode. IIRC zoom mostly only resets after a double tap in other apps.

@michaelstingl michaelstingl modified the milestones: 0.1.0, 0.2.0 Oct 30, 2018
@mneuwert
Copy link
Contributor Author

@felix-schwarz Regarding your comment:

  1. the name of the file is currently shown in the navigation bar and in an overlay. Having it in the navigation bar should be sufficient:

I was thinking that we might add more icons in the navigation bar and therefore introduced an overlay but forgot to remove the file name from navigation bar.

Copy link
Contributor

@felix-schwarz felix-schwarz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing the visual glitches and kudos to a really solid user experience! 👍

I made a few comments but from my perspective, this could also get merged as-is and the issues raised be addressed in a feature/pdfRefinements branch.

With regards to the icons, it'd be good to keep track of who made them and how they are licensed. Did you draw them yourself in the scope of this project, or use third-party ones?

ownCloud/Viewer/PDFViewerViewController.swift Show resolved Hide resolved
ownCloud/Viewer/PDFSearchViewController.swift Outdated Show resolved Hide resolved

guard let currentPageLabel = pdfView.currentPage?.label else { return }

pageCountLabel.text = "\(currentPageLabel) of \(pdf.pageCount)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ownCloud Manual.pdf has "wild" page labels, so I get to see:

  • "1 of 79" on the first page
  • "i of 79" on the third page
  • "1 of 79" on the fifth page
  • "75 of 79" on the last page

I'd like to suggest:

  • using PDFDocument.index(for: page) for this label
  • using PDFPage.label only in the table of contents
  • localizing the string

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felix-schwarz good point!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felix-schwarz however.. I think there is a problem with your suggestion to use PDFDocument.index(for: page) since it returns 0-based index.. so if page numbers start with something like i, ii, iii, 1, this method would return value 3 for page labeled "1".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mneuwert Good point! The first page should be page 1 of course :) … since the y element of the "x of y" text is using the page count, the x should be the page offset (+1) instead of the label to stay consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@felix-schwarz There is still an issue, see ownCloud Manual.pdf: sequence of page label in this document is:
1, 2, i, ii, 1, 2, 3 etc

Copy link
Contributor

@felix-schwarz felix-schwarz Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mneuwert I think for this "[page] of [total]" box at the bottom, PDF page labels are meaningless and prone to be inconsistent and confusing. Let's go for PDFDocument.index(for: page) + 1.

fileprivate let pdfView = PDFView()
fileprivate let thumbnailView = PDFThumbnailView()

fileprivate let containerView = UIStackView()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a UIStackView and putting the PDFView into it will make it hard/impossible to show PDF content "underneath" elements above and below the pdf view like in Apple's Books.

Switching to a UIView for the containerView would make that possible and generally give more room to the content.

ownCloud/Viewer/PDFOutlineViewController.swift Outdated Show resolved Hide resolved
ownCloud/Viewer/PDFTocTableViewCell.swift Outdated Show resolved Hide resolved
self.contentView.addSubview(imageView!)

pageLabel = UILabel()
pageLabel?.backgroundColor = UIColor.clear
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page labels are difficult to read if the page is darker. As far as I can see, Apple Books uses a white (or bright gray?) color here so the page number remains legible even on dark backdrops. Getting that "label" look of Apple Books, though, may require another container view around the label.

@mneuwert
Copy link
Contributor Author

mneuwert commented Nov 16, 2018

@felix-schwarz Regarding icons, I used Google Material icons in PDF which use Apache v2 style license if I remember correctly.

Link to Material icons which also references license:
https://google.github.io/material-design-icons/
http://www.apache.org/licenses/LICENSE-2.0.txt

Copy link
Contributor

@felix-schwarz felix-schwarz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes. The only thing I'd still like to see changed is using the page offset (+1) instead of the page label, which should be a very minor change. The rest is better dealt with in a refinement branch.

Approved! :-)

@jesmrec
Copy link
Contributor

jesmrec commented Nov 19, 2018

Very good job @mneuwert!!. I have noticed a couple of things:

  • In searching mode, the separator appears only with a small set of matches. When you type only a letter (f.ex, an a), the matches are shown with no separator. When you type a more accurate input and returns a smaller set of matches, separator is displayed.

  • Regarding this @felix-schwarz comment:

If I zoom into a page and then tap it, the zoom resets while going in/out of full screen mode. IIRC zoom mostly only resets after a double tap in other apps.

The only way to reestablish original page size after zooming in/out is repainting (change orientation or page up/down). Double tap should do that

@mneuwert
Copy link
Contributor Author

mneuwert commented Nov 19, 2018

@jesmrec Fixed an issue with separator. Looks like zooming with double-tap is broken, when PDFView is configured to use UIPageViewController.

@jesmrec jesmrec added the Approved by QA Approved by QA label Nov 20, 2018
@jesmrec
Copy link
Contributor

jesmrec commented Nov 20, 2018

Approved

@jesmrec jesmrec merged commit e5518a1 into master Nov 20, 2018
@jesmrec jesmrec deleted the feature/pdf_integration branch November 20, 2018 11:43
@jesmrec jesmrec mentioned this pull request Jan 22, 2019
45 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Approved by QA Approved by QA p2-high Escalation, on top of current planning, release blocker
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants